package com.data.permission.rule.process;


import com.data.permission.constrant.CommonConstrant;
import com.data.permission.utils.NetAddressUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.zookeeper.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.IOException;

/**
 * @包名称 com.thrift.distributed.process
 * @类描述 <pre>服务注册器（zk注册）</pre>
 * @作者 zhangbo
 * @创建时间 2019/9/19
 * @版本 1.00
 * @修改记录 <pre>
 *     版本           修改人         修改日期         修改内容描述
 *     -----------------------------------------------------------
 *     1.00           Lenovo        2019/9/19
 *     -----------------------------------------------------------
 * </pre>
 */
@Slf4j
@Service
public class ZKRegistServer implements Watcher {

    @Value("${REGIST.ZOOKEEPER:localhost:2181}")
    private String zookeeperAddress;

    @Value("${PROCESS.PORT:9090}")
    private int servicePort;

    @Value("${ZOOKEEPER.SERVICE.SLEEP.TIME:10000}")
    private int zookeeperServiceSleepTime;

    private ZooKeeper zooKeeper;

    public void regist() {
        while (true) {
            try {
                if(null == zooKeeper) {
                    zooKeeper = new ZooKeeper(zookeeperAddress, zookeeperServiceSleepTime, this);
                    zooKeeper.register(this);
                }
                if (zooKeeper.exists(CommonConstrant.PROCESS_SERVICE_PATH, true) == null) {
                    zooKeeper.create(CommonConstrant.PROCESS_SERVICE_PATH, "".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
                }
                String serviceAddress = NetAddressUtil.getServerIp() + ":" + servicePort;
                String registerPath = CommonConstrant.PROCESS_SERVICE_PATH + "/" + serviceAddress;
                if (zooKeeper.exists(registerPath, true) == null) {
                    zooKeeper.create(registerPath, "".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
                }
                log.info("服务注册成功：{}", registerPath);
                break;
            } catch (InterruptedException e) {
                log.error("线程中断:{}", e);
                Thread.currentThread().interrupt();
            } catch (KeeperException e) {
                try {
                    if(null != zooKeeper) {
                        zooKeeper.close();
                    }
                    zooKeeper = new ZooKeeper(zookeeperAddress, zookeeperServiceSleepTime, this);
                    zooKeeper.register(this);
                } catch (IOException e1) {
                    log.error("重新创建zookeeper对象失败：{}", e1);
                } catch (InterruptedException e1) {
                    log.error("zookeeper关闭连接失败：{}", e1);
                    Thread.currentThread().interrupt();
                }
                log.debug("重新连接异常：{}", e);
            } catch (IOException e) {
                log.error("创建zookeeper对象失败：{}", e);
            }
        }
    }

    @Override
    public void process(WatchedEvent watchedEvent) {
        log.debug("服务监听到事件：{}", watchedEvent.toString());
        if (watchedEvent.getType() == Event.EventType.NodeDeleted) {
            /*监听到节点被删除，重新连接*/
            regist();
        }
    }

}
